
package com.mywork.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mywork.util.IPUtil;
import com.mywork.util.MD5Utils;
import com.mywork.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Aspect
@Component
@Slf4j
@Order(-5)
public class WebLogAspect {

    //定义切点
    @Pointcut("execution(public * com.mywork.controller..*.*(..))")
    public void exec() {
    }

    @Around("exec()")
    public Object aroundLog(ProceedingJoinPoint point) throws Throwable {

        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        long startTime = System.currentTimeMillis();
        Object[] args = point.getArgs();
        Object retVal = point.proceed(args);
        long endTime = System.currentTimeMillis();

        Map<String, String[]> stringMap = md5ImgParam(request.getRequestURI(), new HashMap<>(request.getParameterMap()));
        if (stringMap.size() == 0 && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                stringMap.put("args" + i, new String[]{
                        JSONObject.toJSONString(args[i])
                });
            }
        }
        int bLen = 0;
        int kbLen = 0;

        String header = request.getHeader("content-length");
        if (!StringUtil.isEmpty(header)) {
            int bLenInt = Integer.parseInt(header);
            bLen = bLenInt;
            kbLen = bLenInt / 1024;
        }
        String lenStr = bLen + "b 转换 " + kbLen + "kb";

        log.info("\n\t请求IP: {}\n\t请求路径: {}\n\t请求方式: {}\n\t请求参数: {}\n\t返回值: {}\n\t执行时间: {}\n\t请求大小: {}",
                IPUtil.getIpAddr(request), request.getRequestURL().toString(), request.getMethod(),
                JSONObject.toJSONString(stringMap), JSONObject.toJSONString(retVal), endTime - startTime + "毫秒", lenStr);
        return retVal;
    }

    //处理request中的图片数据
    private Map<String, String[]> md5ImgParam(String requestUrl, Map<String, String[]> parameterMap) {
        String[] imgPaths = parameterMap.get("imgpath");
        String[] list = new String[0];
        if (null != imgPaths && imgPaths.length != 0) {
            List<String> imgPathFinal = new ArrayList<>();
            //获取第一个字符串
            String imgPathStr = imgPaths[0];
            if (imgPathStr.contains("分")) {
                String[] split = imgPathStr.split("分");
                for (String s : split) {
                    if (!StringUtil.isEmpty(imgPathStr)) {
                        String s1 = MD5Utils.MD5Encode(s, "utf-8");
                        imgPathFinal.add(s1);
                    }
                }
                list = imgPathFinal.toArray(new String[split.length]);
            } else if (imgPathStr.contains("|")) {
                String[] split = imgPathStr.split("\\|");
                for (String s : split) {
                    if (!StringUtil.isEmpty(imgPathStr)) {
                        String s1 = MD5Utils.MD5Encode(s, "utf-8");
                        imgPathFinal.add(s1);
                    }
                }
                list = imgPathFinal.toArray(new String[split.length]);
            } else {
                if (!StringUtil.isEmpty(imgPathStr)) {
                    list = new String[1];
                    list[0] = MD5Utils.MD5Encode(imgPathStr, "utf-8");
                }
            }
            parameterMap.put("imgpath", list);
        }


        return parameterMap;

    }

    private String getMethodInfo(JoinPoint point) {
        ConcurrentHashMap<String, Object> info = new ConcurrentHashMap<>(3);

        info.put("class", point.getTarget().getClass().getSimpleName());
        info.put("method", point.getSignature().getName());

        String[] parameterNames = ((MethodSignature) point.getSignature()).getParameterNames();
        ConcurrentHashMap<String, String> args = null;

        if (Objects.nonNull(parameterNames)) {
            args = new ConcurrentHashMap<>(parameterNames.length);
            for (int i = 0; i < parameterNames.length; i++) {
                String value = point.getArgs()[i] != null ? point.getArgs()[i].toString() : "null";
                args.put(parameterNames[i], value);
            }
            info.put("args", args);
        }

        return JSONObject.toJSONString(info);
    }


}
